from os import path
import sys
sys.path.append("..")
from src.TextDataset import *
from src.visualisations import *
from src.api import *
import scipy.stats as stats
[nltk_data] Downloading package stopwords to /Users/gabrielnativel- [nltk_data] fontaine/nltk_data... [nltk_data] Package stopwords is already up-to-date!
data = TextDataset(('../data/testing_set.json', '../data/training_set.json'), 'sentence', 'intent')
Loaded 7100 rows
Commençons par analyser le jeu de données qui nous a été fourni.
Ce jeu de données contient au total 7100 phrases étiquettées en 8 classes:
histogram_intents(data._data)
La première observation étonnante se trouve dans la répartition des phrases dans les différentes classes. Sur la totalité du jeu de données, on compte 3852 phrases étiquettées dans la classe 'irrelevant', soit environ 6 fois plus que pour la classe 'purchase' qui est la classe qui contient le plus d'entrées après 'irrelevant' et 32 fois plus que la classe 'provide-showtimes' qui contient le moins d'entrée.
words_by_sentences(data._data)
Lorsqu'on compte le nombre de mots par phrases, on constate que la majorité des phrases comptent moins de 15 mots.
display_box_plot_nb_words(data._data)
En moyenne, les phrases dans chaque intent du jeu de données contiennent entre 10 et 15 mots. On note une exception pour la classe "irrelevant" qui semble contenir des phrases plus courtes en moyenne. Cette différence d'observation peut s'expliquer par le nombre plus important de phrases dans la classe irrelevant.
Etudions maintenant le modèle de nos prédécesseurs.
pred, prob = multiple_prediction("http://localhost:8080/api/intent", data._data)
metrics_analysis(pred, data._data['intent'], False)
| find-train | irrelevant | find-flight | find-restaurant | purchase | find-around-me | provide-showtimes | find-hotel | |
|---|---|---|---|---|---|---|---|---|
| find-train | 87 | 67 | 2 | 0 | 8 | 0 | 0 | 0 |
| irrelevant | 1 | 4431 | 0 | 10 | 49 | 18 | 1 | 19 |
| find-flight | 4 | 80 | 61 | 0 | 11 | 3 | 1 | 6 |
| find-restaurant | 0 | 201 | 0 | 339 | 7 | 14 | 0 | 1 |
| purchase | 0 | 292 | 1 | 4 | 413 | 15 | 0 | 2 |
| find-around-me | 0 | 218 | 0 | 8 | 43 | 178 | 0 | 3 |
| provide-showtimes | 0 | 87 | 0 | 0 | 2 | 4 | 38 | 0 |
| find-hotel | 0 | 167 | 0 | 9 | 8 | 14 | 0 | 173 |
| Accuracy | 0.805634 |
| Precision | 0.862425 |
| Recall | 0.524944 |
| F-Score | 0.652638 |
80% des observations totales sont correctements prédites, c'est un résultat qui semble correct mais dont il faut se méfier dans la mesure où le jeux de données semble très déséquilibré.
86% de précision, indique un taux de faux positifs assez faible.
53% de rappel (ou sensibilité), donne le taux d'observations correctement étiquettées. On observe donc que presque la moitié des prédictions sont fausses. Ce résultats est fortement lié à une mauvaise classification des irrelevant, accentué par le très grand nombre d'éléments de cette classe.
multiple_roc_curves(data._data, prob, False)
Dans le cadre d'une classification multi-classe, nous avons choisi de réprésenter une courbe ROC par classe. Plus l'aire sous la courbe est grande, moins le classifieur fait d'erreurs, on peut observer les modifications de la sensibilité et de la spécificité en fonction des variations du seuil de chaque variable. Les seuils les plus intéressants correspondent au coin supérieur gauche de la figure. Ceci nous permet donc de définir une plage d'utilisation pour ce modèle. On peut estimer que la prédiction est satisfaisante au délà du seuil de 0.75. On pourrait éventuellement affiner ce seuil pour chaque variable.
multiple_average_precision(data._data, prob)
L'aire sous les courbes de cette figure indique à la fois une précision et un rappel élevés. On peut ainsi observer des performances différentes selon les intents prédits